<?php
/**
 *  The default order of searching for template files:
 *  - site templates directory (lib/templates), "moduleName-tplName"
 *  - current module
 *  - parent module, parent of parent etc
 *  - Yz/templates
 *  See the $templatePath variable
 *
 */
abstract class Yz_Template_Native
    extends Yz_Template_Abstract
    implements Yz_Template_Interface
{

    /**
     *      the common locations of templates:
     *
     */
    // site-specific
    const SITE_TEMPLATE_DIR = 'templates/';
    // system (admin)
    const SYS_TEMPLATE_DIR = 'Yz/templates/';

    /** Override the default filename for the template
     *  @var string|null
     */
    protected $filename;

    protected $boundaryMark = "\n<!-- %{BEGIN} %{class} -->\n";

    protected $templateDir;

    /**************************************
     *      Public methods            *
     **************************************/


    public function useSystemTemplates()
    {
        $this->templateDir = self::SYS_TEMPLATE_DIR;
        return parent::useSystemTemplates();
    }

    /**************************************
     *      Protected methods            *
     **************************************/

    protected function doRender()
    {
        debug();

        $name = $this->filename ?: $this->name();

        $bm = $this->boundaryMark;

        $file = $this->findTemplate($name);
        extract($this->value, EXTR_PREFIX_ALL, 'var');
        ob_start();
        if (null !== $bm) {
            $class = $this->className();
            print Yz_String::replaceVars($bm,array(
                'BEGIN' => 'BEGIN',
                'class' => $class,
                ));
        }
        include("$file");
        if (null !== $bm) {
            print Yz_String::replaceVars($bm,array(
                'BEGIN' => 'END',
                'class' => $class,
                ));
        }
        return ob_get_clean();
    }

    /**
     *  @todo search lib/templates for {module}-{name}.php or lib/templates/{module}/ ???
     *  @return Yz_File
     *  @throw template-not-found
     */
    protected function findTemplate($name)
    {
        debug();

        $dir = $this->templateDir;
        if (null === $dir) {
            $dir = Yz::getInstalledNamespaces()->offsetGet(0)
                . '/'
                . self::SITE_TEMPLATE_DIR;
        }

        // ring 1: search common templates
        $file = new Yz_File( $dir . $name . '.php');
        if ($file->isFile()) {
            return $file;
        }

        // leave this algorithm as follows because:
        // * a template class can be derived from a class with a different name
        // * a template can be defined in this module only, or have a different functionality from
        // the same-named template in parent module,
        // so searching upwards is not desired
        $class = $this;
        while ($ns = $class::namespaceName()) {
            $path = strtr($ns, '\\', '/');
            $file = new Yz_File( $path . '/templates/' . $name . '.php');
            if ($file->isFile()) {
                return $file;
            }
            $class = get_parent_class($class);
            assert('is_subclass_of($class,"Yz_Template_Interface")');
        }
        $ex = new Yz_Template_Exception();
        throw $ex->withArgs(array("name"=>$name));
    }


}
